
import time, threading, socket, Queue, re

HOST = ''
PORT = 50007

VALID_CMD = ["QUIT", "SHUTDOWN", "START", "STARTALL", "PAUSE", "RESUME", "RELOAD", 
             "STATUS", "GETID", "GETVARS", "GETDEFS", 
             "FORCEREQ", "GETCONF", "IDENT", "SETQUERY",
             "HELP"]

class server(threading.Thread):
      def __init__(self, queue, logger):
          self.__queue = queue
          self.logger = logger

          threading.Thread.__init__(self)
          try:
             self.socketSrv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
             self.socketSrv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
          except:
             raise IOError, "No puc crear el socket del servidor ..."
             pass

          self.lastCmd = ()
          self.aturaTot = False
          self.clients = []

      def parseCmd(self, data):
          data = data.upper().rstrip()
          cmdTrobada = re.search(r"^\$([A-Z]+)(?:|.)([0-9]*)\$", data)
          
          self.lastCmd = ()
          if cmdTrobada:
             self.lastCmd = cmdTrobada.groups()

          return cmdTrobada 

      def beginDialog(self, conn):
          ini = conn.recv(2)
          if ini == '#$':
             conn.send('$#')
          return(ini == '#$')

      def handleClient(self, clientSock):
          peer = clientSock.getpeername()

          try:
              if not self.beginDialog(clientSock):
                 return
          except Exception, e:
              self.logger.error(str(e))
              clientSock.close()
              return

          connectat = True
          while connectat:
              try:
                 data = clientSock.recv(4096)
              except socket.timeout:
                 continue
              except socket.error:
                 self.logger.error("Server shutdown")
                 return
              except:
                 break
              if not len(data):
                 break

              if not self.parseCmd(data):
                 self.logger.error("Invalid format command")
                 clientSock.send("FORMAT_ERROR\r")
                 continue

              self.currConn = clientSock
              (cmd, args) = self.lastCmd

              if not cmd in VALID_CMD:
                 self.logger.error("Invalid command")
                 clientSock.send("ERR\r")
                 continue

              self.__queue.put((self.lastCmd, clientSock))

              if cmd == 'SHUTDOWN':
                 clientSock.send("BYE!\r")
                 self.aturaTot = True
                 connectat = False 
              else:
                 if cmd == 'QUIT':
                    clientSock.send("DISCONNECTED!\r")
                    connectat = False
                 else:
                    if cmd == 'HELP':
                       clientSock.send(" ".join(VALID_CMD))
                       clientSock.send("\r")
     
          self.logger.debug("Client desconnectat ...")
          clientSock.close()

      def __disconnectAllClients__(self):
          self.socketSrv.close()
          for sock in self.clients:
              sock.close()
 
      def run(self):
          try:
             self.socketSrv.bind((HOST, PORT))
             self.socketSrv.listen(100)
          except:
             raise IOError, "Aquest socket ja esta agafat per algu altre"
             pass 
          else:
             while not self.aturaTot:
                   try:
                       clientSock, clientAddr = self.socketSrv.accept()
                       clientSock.settimeout(1)
                   except KeyboardInterrupt:
                       self.__disconnectAllClients__()
                       break
                   except:
                       traceback.print_exc()
                       continue

                   self.logger.debug("Client connectat %(add)s... " % {"add": clientAddr})

                   self.clients.append(clientSock)
                   t = threading.Thread(target = self.handleClient, args = [clientSock])
                   t.setDaemon(1)
                   t.start()
                 
             self.__disconnectAllClients__()
             self.socketSrv.close()    
